home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1997 August / Walnut Creek CDROM.7z / LISTINGS / V_13_04 / CHAPMAN2 / CHAPMAN2.ZIP / FINDMSGS.C < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-26  |  8.2 KB  |  291 lines

  1. /* findmsgs.c - find keyed error messages in C++ modules */
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include "clexer.h"
  7.  
  8. #ifdef __ZTC__
  9. #include <dos.h>                        /* for WILDCARDS */
  10. WILDCARDS                               /* link in wildcard expansion (ZTC) */
  11. #endif  /* __ZTC__ */
  12.  
  13. extern FILE *yyin;
  14. char *yytext;
  15.  
  16. #ifdef __STDC__
  17. int yyrestart(FILE *);                  /* flex function definitions */
  18. int yylex(void);
  19. void parsefile(const char *filename);   /* our functions */
  20. void printstring(const char *filename,int linenum,const char *tok);
  21. #else
  22. int yyrestart(),yylex(),parsefile(),printstring();
  23. #ifndef EXIT_SUCCESS
  24. #define EXIT_SUCCESS 0
  25. #endif
  26. #endif  /* __STDC__ */
  27.  
  28. #ifdef __STDC__
  29. int main(int argc,char *argv[])
  30. #else
  31. int main(argc,argv)
  32. int argc;
  33. char *argv[];
  34. #endif  /* __STDC__ */
  35. {
  36.     /* search for string constants in the input files (default: stdin) */
  37.     /* and write all string constants to stdout. */
  38.  
  39.     FILE *infile;
  40.     int i,firstfile = 1;
  41.  
  42.     if (argc == 1) {
  43.         parsefile("");                  /* default: stdin */
  44.         return EXIT_SUCCESS;
  45.     }
  46.     for (i = 1; i < argc; ++i) {
  47.         infile = fopen(argv[i],"r");
  48.         if (infile == 0) {
  49.             fprintf(stderr,"Unable to read file %s\n",argv[i]);
  50.             continue;
  51.         }
  52.  
  53.         /* due to a bug in flex 2.3.6, we can't use yyrestart() the */
  54.         /* first time. thus we just assign to yyin (which was a pointer */
  55.         /* to stdin). */
  56.  
  57.         if (firstfile)
  58.             yyin = infile;
  59.         else
  60.             yyrestart(infile);
  61.         parsefile(argv[i]);
  62.         fclose(infile);
  63.         firstfile = 0;
  64.     }  /* end of for(i) */
  65.  
  66.     return EXIT_SUCCESS;
  67.  
  68. }  /* end of main() */
  69.  
  70. #ifdef __STDC__
  71. void parsefile(const char *filename)
  72. #else
  73. parsefile(filename)
  74. char *filename;
  75. #endif  /* __STDC__ */
  76. {
  77.     /* parse the input file, extracting all string constants. */
  78.  
  79.     int val,last_val,last_linenum;
  80.     char buf[MAXSTRINGLEN];
  81.  
  82.     column = 0;
  83.     linenum = 1;
  84.     last_val = ERROR;
  85.     last_linenum = -1;
  86.     buf[0] = '\0';
  87.  
  88.     while ((val = yylex()) != 0) {
  89.  
  90.         /* adjacent string constants catenate, so we must collect them. */
  91.  
  92.         if (val == STRING) {
  93.             if (last_linenum < 0)       /* remember where it started */
  94.                 last_linenum = linenum;
  95.  
  96.             /* we assume there is room in the buffer. */
  97.  
  98.             strcat(buf,lexstringtok);  /* save it */
  99.             last_val = val;
  100.         }
  101.  
  102.         /* there's a hole in the scanner; it returns ERROR tokens */
  103.         /* sometimes. if we get one we ignore it. */
  104.  
  105.         else if (val != ERROR) {
  106.             if (last_val == STRING) {
  107.                 printstring(filename,last_linenum,buf);
  108.                 buf[0] = '\0';          /* clear buffer */
  109.             }  /* end of if(was string) */
  110.             last_linenum = -1;
  111.             last_val = val;
  112.         }  /* end of else(not string now) */
  113.     }  /* end of while() */
  114.  
  115.     /* watch for a trailing string constant. */
  116.  
  117.     if (last_val == STRING)
  118.         printstring(filename,last_linenum,buf);
  119.  
  120. }  /* end of parsefile() */
  121.  
  122. #ifdef __STDC__
  123. char escape_char(char c)
  124. #else
  125. char escape_char(c)
  126. char c;
  127. #endif  /* __STDC__ */
  128. {
  129.     /* return the ASCII equivalent of a C escape sequence. the '\' has */
  130.     /* been matched already. */
  131.  
  132.     switch(c) {
  133. #ifdef __STDC__
  134.     case 'a':                           /* audible alarm */
  135.         return '\a';
  136. #endif  /* __STDC__ */
  137.     case 'f':                           /* form feed */
  138.         return '\f';
  139.     case 'r':                           /* carriage return */
  140.         return '\r';
  141.     case 'v':                           /* vertical tab */
  142.         return '\v';
  143.     case 'b':                           /* backspace */
  144.         return '\b';
  145.     case 'n':                           /* newline */
  146.         return '\n';
  147.     case 't':                           /* tab */
  148.         return '\t';
  149.     default:                            /* something ordinary quoted */
  150.         return c;
  151.     }  /* end of switch() */
  152.  
  153.     /* NOTREACHED */
  154.  
  155. }  /* end of escape_char() */
  156.  
  157. #ifdef __STDC__
  158. char octalchar(char c,const char **tok)
  159. #else
  160. char octalchar(c,tok)
  161. char c,**tok;
  162. #endif  /* __STDC__ */
  163. {
  164.     /* return the character specified by the octal sequence. not too */
  165.     /* bright about 8 and 9 appearing in the string. */
  166.  
  167.     int i,result = c - '0';
  168.  
  169.     for (i = 0; i < 3 && isdigit(**tok); ++i) {
  170.         result = result * 8 + (**tok - '0');
  171.         ++*tok;                         /* advance character pointer */
  172.     }
  173.     return (char) result;
  174.  
  175. }  /* end of octalchar() */
  176.  
  177. #ifdef __STDC__
  178. int hexval(char c)
  179. #else
  180. int hexval(c)
  181. char c;
  182. #endif  /* __STDC__ */
  183. {
  184.     /* convert a character to its hexadecimal equivalent. assumes */
  185.     /* isxdigit(c) is true. */
  186.  
  187.     if (isdigit(c))
  188.         return c - '0';
  189.     return toupper(c) - 'A' + 10;
  190.  
  191. }  /* end of hexval() */
  192.  
  193. #ifdef __STDC__
  194. char hexchar(char c,const char **tok)
  195. #else
  196. char hexchar(c,tok)
  197. char c,**tok;
  198. #endif  /* __STDC__ */
  199. {
  200.     /* return the character specified by the hex sequence. */
  201.  
  202.     int i,result = hexval(c);
  203.  
  204.     for (i = 0; i < 2 && isxdigit(**tok); ++i) {
  205.         result = result * 16 + hexval(**tok);
  206.         ++*tok;                         /* advance character pointer */
  207.     }
  208.     return (char) result;
  209.  
  210. }  /* end of hexchar() */
  211.  
  212. #ifdef __STDC__
  213. void printstring(const char *filename,int linenum,const char *tok)
  214. #else
  215. printstring(filename,linenum,tok)
  216. char *filename;
  217. int linenum;
  218. char *tok;
  219. #endif  /* __STDC__ */
  220. {
  221.     /* if the string constant looks like an err_mgr message, print */
  222.     /* it along with its location. */
  223.  
  224.     char *buf,*s,c,esc_c;
  225. #ifdef __STDC__
  226.     const char *t;
  227. #else
  228.     char *t;
  229. #endif  /* __STDC__ */
  230.  
  231.     if (*tok != '$')
  232.         return;
  233.     ++tok;                              /* skip '$' - doesn't go in dict */
  234.     while (isspace(*tok))               /* skip leading blanks */
  235.         ++tok;
  236.     t = tok;
  237.     while (isalpha(*t) || isdigit(*t) || *t == '_')  /* identifier? */
  238.         ++t;
  239.     while (isspace(*t))                 /* skip trailing blanks */
  240.         ++t;
  241.     if (*t != ':')                      /* if next char not ':', can't */
  242.         return;                         /* be dictionary message */
  243.  
  244.     /* replace any '\\' sequences with their ASCII equivalents and */
  245.     /* prefix embedded newlines ("\n" or an actual '\n' character) */
  246.     /* with a '\\' so that the dictionary reader will merge the lines */
  247.     /* properly. */
  248.  
  249.     s = buf = malloc(strlen(tok) * 2 + 1);  /* may grow a bit in the process */
  250.     while ((c = *tok++) != '\0') {
  251.         if (c == '\n') {
  252.             *s++ = '\\';
  253.             *s++ = c;
  254.         }
  255.         else if (c == '\\') {
  256.             c = *tok++;
  257.             if (c == '\0')
  258.                 break;
  259.             if (isdigit(c))             /* octal character specification */
  260.                 *s++ = octalchar(c,&tok);  /* advance tok too */
  261.             else if (c == 'x')          /* hex character specification */
  262.                 *s++ = hexchar(c,&tok);   /* advance tok too */
  263.             else {
  264.                 esc_c = escape_char(c);
  265.                 if (esc_c == '\n')      /* quote newlines made in C */
  266.                     *s++ = '\\';        /* string constants with "\n" */
  267.                 *s++ = esc_c;
  268.             }
  269.         }  /* end of if('\\') */
  270.         else
  271.             *s++ = c;
  272.     }  /* end of while(c) */
  273.  
  274.     /* last but not least don't quote the final newline, if there is one. */
  275.     /* by definition there is a newline at the end of each complaint */
  276.     /* dictionary entry, and we don't want two. */
  277.  
  278.     if (s > (buf + 1) && s[-1] == '\n') {
  279.         --s;
  280.         s[-1] = '\n';                   /* overwrite final '\\' */
  281.     }
  282.     *s = '\0';                          /* terminate string */
  283.  
  284.     if (*filename)
  285.         printf("# file %s line %d\n%s\n",filename,linenum,buf);
  286.     else                                /* coming from stdin */
  287.         printf("# line %d\n%s\n",linenum,buf);
  288.     free(buf);
  289.  
  290. }  /* end of printstring() */
  291.